package org.lex.net;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.DateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class NetworkServer implements Runnable {
	private ServerSocket serverSocket = null;
	private int port = 0;
	private ExecutorService pool = null;
	private RequestHandler requestHandler = null;

	public static void main(String[] args) throws IOException {
		NetworkServer server = new NetworkServer(2007);
		server.setRequestHandler(new EchoRequestHandler());
		server.startServer();
	}

	public NetworkServer(int port) {
		this.port = port;
	}

	public void setRequestHandler(RequestHandler handler) {
		this.requestHandler = handler;
	}

	public final void startServer() throws IOException {
		serverSocket = new ServerSocket(port);
		pool = Executors.newCachedThreadPool();
		pool.execute(this);
		System.out.println("Server started, listening on port: " + port);
	}

	public void closeClose() throws IOException {
		serverSocket.close();
		serverSocket = null;
		pool.shutdown();
		pool.shutdownNow();
		pool = null;
	}

	public final void run() {
		try {
			do {
				final Socket client = serverSocket.accept();
				this.printClientInformation(client);
				pool.execute(new Runnable() {
					public void run() {
						try {
							requestHandler.respond(client);
						} catch (Exception e) {
						}
					}
				});
			} while (true);
		} catch (Exception e) {
			e.printStackTrace(System.err);
		}
	}

	private DateFormat dateFormat = DateFormat.getDateTimeInstance();
	private Date date = new Date();

	private void printClientInformation(Socket client) {
		date.setTime(System.currentTimeMillis());
		System.out.print(dateFormat.format(date));
		System.out.print(" ");
		System.out.println(client);
	}
}
